#include <assert.h>
#include <stdio.h>
#include <unistd.h> /* for readlink() Func */
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <dirent.h> /* for NAME_MAX Macro */
#include <limits.h> /* for PATH_MAX Macro */
#include "unit_test.h"

#include "get_filename_from_fd.h"


/** 
 * For getting the filename of fd , 
 * we try to read the path of "/proc/{pid}/fd/{fd} symlink" 
 */
int get_filename_from_fd(int fd , char * filename_p , unsigned int size){

	/**
	 * fd(0): stdin
	 * fd(1): stdout
	 * fd(2): stderr
	 */

	int retval = 0;
	char sym_name [PATH_MAX+NAME_MAX+1] = {0};
	char file_name[PATH_MAX+NAME_MAX+1] = {0};
	pid_t	mypid = 0;

	assert(filename_p);

	if( 0 > fd ){
		fprintf( stderr , "the fd is less than 0\n");
		fflush( stderr );
		retval = -1;
		goto out;
	}

	mypid = getpid();

	sprintf( sym_name , "/proc/%d/fd/%d" , mypid , fd );

	retval = readlink( sym_name , file_name , PATH_MAX+NAME_MAX );
	if( -1 == retval ){
		fprintf( stderr , "readlink failed\n" );
		fflush( stderr );
		retval = -2;
		goto out;
	}
	
	if( retval > size ){
		fprintf( stderr , "length of buffer is not enough\n" );
		fflush( stderr );
		retval = -3;
		goto out;
	}

	strncpy( filename_p , file_name , retval );
out:
	return retval;
}
int __UNIT_TEST_MAIN(){
	char file[1000]={0};
	int len;
	memset(file  , 0 , 1000);
	len  = get_filename_from_fd( 0 , file , 1000); /* stdin */
	printf("%s %d\n" , file , len);
	memset(file  , 0 , 1000);
	len = get_filename_from_fd( 1 , file , 1000); /* stdout */
	printf("%s %d \n" , file ,len);
	memset(file  , 0 , 1000);
	len = get_filename_from_fd( 2 , file , 1000); /* stderr */
	printf("%s %d\n" , file , len);
	memset(file  , 0 , 1000);
	len = get_filename_from_fd( 3 , file , 1000); /* test a error case */
	printf("%s %d\n" , file , len);
	
	int fd = open( "/var/test_func.txt" , O_CREAT|O_RDONLY );
	if( 0 > fd){
		perror( "open failed\n" );
		exit( -1 );
	}
	len = get_filename_from_fd( fd , file , 1000 ); /* a opend file descript */
	printf( "%s %d\n" , file , len);
	close( fd );	
	return 0;
}
